package com.iretailer.report.analyze.netty;


import com.iretailer.report.analyze.commonUtil.Analyze;
import com.iretailer.report.analyze.commonUtil.ResponeResultType;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.handler.codec.http.multipart.DefaultHttpDataFactory;
import io.netty.handler.codec.http.multipart.HttpDataFactory;
import io.netty.util.CharsetUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.SocketAddress;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Auther: xjw
 * @Date: 2018/12/5 10:41
 * @Description:
 */
public class NettyServerHandler extends SimpleChannelInboundHandler<Object> {

    private static Logger log = LoggerFactory.getLogger(NettyServerHandler.class);


    private static final HttpDataFactory httpDataFactory =
            new DefaultHttpDataFactory(DefaultHttpDataFactory.MINSIZE);

    private AtomicInteger connectNum;

    public NettyServerHandler(AtomicInteger connectNum) {
        this.connectNum = connectNum;
    }

    @Override
    protected void messageReceived(ChannelHandlerContext ctx, Object msg) throws Exception {

        try {
            long startTime = System.currentTimeMillis();
            //接收到完成的http请求
//        Channel channel = ctx.channel();
            SocketAddress remotAddr = ctx.channel().remoteAddress();
//        System.out.println("连接的远程地址为：" + remotAddr.toString());
            if (msg instanceof HttpRequest) {
                HttpRequest httpRequest = (HttpRequest) msg;
                HttpMethod method = httpRequest.method();
//            HttpHeaders httpHeaders = httpRequest.headers();
//            String connection = httpHeaders.getAndConvert("Connection");
//            log.info("Connection -- " + connection);

                switch (method.toString()) {
                    case "POST":
                        ResponeResultType status = ResponeResultType.getBadRequest(ResponeResultType.CFLType.CLOSE);
                        String content = null;
                        Map<String, Object> paramsMap = new HashMap<>();
                        paramsMap.put("remoreAddr", remoreAddr(remotAddr));
                        String path = analyzePath(httpRequest.uri(), paramsMap);
                        paramsMap.put("path", path);
                        Analyze keyType = NettyHttpServer.pathMap.get(path);
                        if (keyType != null) {
                            status = keyType.nettyAnalyze(paramsMap, msg);
                        } else {
                            log.error(" path is not find | {}", path);
                        }

                        send(content, ctx, status);
                        break;
                    default:
                        send(null, ctx, ResponeResultType.getOkRequest(ResponeResultType.CFLType.CLOSE));
                        break;
                }

            }
            long endTime = System.currentTimeMillis();
            log.info(" connect {}  -----  {}ms ", remotAddr, endTime - startTime);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        super.exceptionCaught(ctx, cause);
        Channel channel = ctx.channel();

        if (channel.isActive()) ctx.close();
    }

    /*
     * 建立连接时，返回消息
     */
    public void channelActive(ChannelHandlerContext ctx) {

    }

//    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
//        super.channelRegistered(ctx);
//        connectNum.incrementAndGet();
//        log.error("===== current connected : " + connectNum.get());
//    }
//    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
//        super.channelUnregistered(ctx);
//        connectNum.decrementAndGet();
//        System.out.println("----- current connected : " + connectNum.get());
//    }


    /**
     * 返回结果
     *
     * @param content
     * @param ctx
     * @param status
     */
    private void send(String content, ChannelHandlerContext ctx, ResponeResultType status) {
        FullHttpResponse response = null;
        if (content == null) {
            response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status.getHrs());
            response.headers().set(HttpHeaderNames.CONTENT_LENGTH, "0");
        } else {
            response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status.getHrs(),
                    Unpooled.copiedBuffer(content, CharsetUtil.UTF_8));
            response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain;charset=UTF-8");
        }

        response.headers().set(HttpHeaderNames.CONNECTION, "close");

        ctx.writeAndFlush(response).addListener(status.getCfl());
    }

    private String remoreAddr(SocketAddress socketAddress) {
        if (socketAddress != null) {
            String s = socketAddress.toString();
            int index;
            if ((index = s.indexOf(":")) > 0) {
                return s.substring(1, index);
            }
            return s.substring(1);
        }

        return null;
    }

    private String analyzePath(String path, Map<String, Object> paramsMap) {
        int index;
        if ((index = path.indexOf("?")) > -1) {
            String paramStr = path.substring(index + 1);
            String[] paramArr = paramStr.split("&");
            for (int i = 0, len = paramArr.length; i < len; i++) {
                String[] pa = paramArr[i].split("=");
                paramsMap.put(pa[0], pa[1]);
            }
            return path.substring(0, index);
        } else {
            return path;
        }
    }

}
